package com.stevens.triangles;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TestTriangles 
{
	
	@SuppressWarnings({ "serial" })
	
	public static void main(String[] args) throws Exception 
	{
		final double[] rightIsoscelesTriangle = {1,1,Math.sqrt(2)};
		final double[] rightScaleneTriangle = {3,4,5};
		final double[] scaleneTriangle = {2,4,5};
		final double[] isoscelesTriangle = {4,4,5};
		final double[] equilateralTriangle = {2,2,2};
		final double[] tooManySides = {1,2,3,4};
		final double[] tooFewSides = {1,2};
		final double[] negativeSide = {3, -4, 5};
		final double[] zeroSide = {3, 4, 0};
		final double[] invalidTriangle = {10,20,30};
		final double[] rightTriangle = {10.1, 20.2, 22.584};
		final double[] bigIsosceles = {1234567890000.0, 9876543210000.0, 9876543210000.0};
		
		// Specify the test cases as a hash map.
		Map<double[], String> testCases = new HashMap<double[], String>()
		{
			{
				put(rightIsoscelesTriangle, TrianglesBase.kIsoscelesRightTriangle);
				put(rightScaleneTriangle, TrianglesBase.kScaleneRightTriangle);
				put(scaleneTriangle, TrianglesBase.kScaleneTriangle);
				put(isoscelesTriangle, TrianglesBase.kIsoscelesTriangle);
				put(equilateralTriangle, TrianglesBase.kEquilateralTriangle);
				put(tooManySides, TrianglesBase.kTooManySidesError);
				put(tooFewSides, TrianglesBase.kTooFewSidesError);
				put(negativeSide, TrianglesBase.kInvalidSideError);
				put(zeroSide, TrianglesBase.kInvalidSideError);
				put(invalidTriangle, TrianglesBase.kInvalidTriangleError);
				put(rightTriangle, TrianglesBase.kScaleneRightTriangle);
				put(bigIsosceles, TrianglesBase.kIsoscelesTriangle);
			}
		};
		
		// Assemble a list of all classes to test.
		List<Class<?>> classesToTest = new ArrayList<Class<?>>()
		{
			{
				add(RobTriangles.class);
				add(PiotrTriangles.class);
				add(JamieTriangles.class);
			}
		};
		
		for (Class<?> classToTest : classesToTest)
		{
			// Use Reflection to get the constructor for the given class
			System.out.print("Testing " + classToTest.getName() + ": ");
			Class<?> constructorParams[] = new Class[1];
			constructorParams[0] = double[].class;
            Constructor<?> constructor = classToTest.getConstructor(constructorParams);
            
			for (double[] testSideLengths : testCases.keySet())
			{
				// use Reflection to instantiate the desired Triangles class
				Object constructorArguments[] = new Object[1];
	            constructorArguments[0] = testSideLengths;
	            TrianglesBase tri = (TrianglesBase) constructor.newInstance(constructorArguments);

	            // Actually run the test case for the new instance
	            String actual = tri.kindOfTriangle();
				String expected = testCases.get(testSideLengths);
				
				// Evaluate the result by performing a simple string comparison of actual vs. expected
				if (!expected.equals(actual)) 
				{
					System.out.println();
					System.err.println("ERROR: Expected [" + expected + "], but was [" + actual + "], for input " + Arrays.toString(testSideLengths));
					System.exit(-1);
				}
				System.out.print(".");
			}
			System.out.println();
		}
		
		System.out.println("Tests passed.");
	}
	
}